package com.naiterui.ehp.bs.cms.modules.user.controller;

import java.io.IOException;
import java.util.List;
import java.util.Objects;

import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.naiterui.ehp.bp.constants.SwaggerTag;
import com.naiterui.ehp.bp.security.annotation.SysLog;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.support.exception.PublicService;
import com.naiterui.ehp.bp.support.exception.ResponseVO;
import com.naiterui.ehp.bs.cms.common.controller.AbstractController;
import com.naiterui.ehp.bs.cms.common.vo.PageParamsVO;
import com.naiterui.ehp.bs.cms.common.vo.PageVO;
import com.naiterui.ehp.bs.cms.modules.common.service.ICityService;
import com.naiterui.ehp.bs.cms.modules.common.vo.CityVO;
import com.naiterui.ehp.bs.cms.modules.user.feign.DoctorFeignClient;
import com.naiterui.ehp.bs.cms.modules.user.service.IDoctorService;
import com.naiterui.ehp.bs.cms.modules.user.vo.ConsultCommentVO;
import com.naiterui.ehp.bs.cms.modules.user.vo.ConsultComplaintVO;
import com.naiterui.ehp.bs.cms.modules.user.vo.DepartmentVO;
import com.naiterui.ehp.bs.cms.modules.user.vo.DoctorDetailsVO;
import com.naiterui.ehp.bs.cms.modules.user.vo.DoctorPageVO;
import com.naiterui.ehp.bs.cms.modules.user.vo.HospitalVO;
import com.naiterui.ehp.bs.cms.modules.user.vo.LoginLogVO;
import com.naiterui.ehp.bs.cms.modules.user.vo.OcrParamVO;
import com.naiterui.ehp.bs.cms.modules.user.vo.SaveNumberParamVO;
import com.naiterui.ehp.bs.cms.modules.user.vo.StandardDictVO;
import com.naiterui.ehp.bs.cms.modules.user.vo.record.RecordInfoVO;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@AllArgsConstructor
@RestController
@Api(tags = {SwaggerTag.CMS + SwaggerTag.USER})
@RequestMapping("/user/doctor")
public class DoctorController extends AbstractController {

    private final ICityService cityService;
    private final IDoctorService doctorService;
    private final DoctorFeignClient doctorFeignClient;

    /**
     * 列表
     *
     * @return
     */
    @ApiOperation(value = "医生列表")
    @SysLog("医生列表")
    @GetMapping("/list")
    @PreAuthorize("@p.check('user:doctor:list')")
    public PageVO<DoctorPageVO> list(PageParamsVO pageParamsVO, DoctorPageVO doctorVO) {
        return doctorService.queryPage(pageParamsVO, doctorVO);
    }

    @ApiOperation(value = "医生详情")
    @ApiImplicitParam(name = "doctorId", value = "医生id", required = true, dataType = "long", paramType = "path")
    @SysLog("医生详情")
    @GetMapping("/{doctorId}")
    @PreAuthorize("@p.check('user:doctor:detail')")
    public DoctorDetailsVO get(@PathVariable("doctorId") Long doctorId) {
        return doctorService.getDoctorDetailsVO(doctorId);
    }

    /**
     * 评价记录
     */
    @SysLog("评价记录")
    @ApiOperation("评价记录")
    @ApiImplicitParam(name = "doctorId", value = "医生id", required = true, dataType = "long", paramType = "query")
    @GetMapping(value = "consult/comment/list")
    @PreAuthorize("@p.check('user:doctor:list')")
    public PageVO<ConsultCommentVO> commentList(Long doctorId, PageParamsVO pageParamsVO) throws BusinessException {

        return doctorService.findCommentByDoctor(doctorId, pageParamsVO);
    }


    /**
     * 投诉记录
     */
    @SysLog("投诉记录")
    @ApiOperation("投诉记录")
    @ApiImplicitParam(name = "doctorId", value = "医生id", required = true, dataType = "long", paramType = "query")
    @GetMapping(value = "consult/complaint/list")
    @PreAuthorize("@p.check('user:doctor:list')")
    public PageVO<ConsultComplaintVO> complaintList(Long doctorId, PageParamsVO pageParamsVO) throws BusinessException {

        return doctorService.findComplaintByDoctor(doctorId, pageParamsVO);
    }

    @SysLog("医生认证")
    @PostMapping("/audit/auth")
    @PreAuthorize("@p.check('user:doctor:audit')")
    public void authAudit(@RequestBody String body) throws BusinessException {
        log.info("医生认证审核：body={}",body);
        doctorFeignClient.authAudit(body);
    }

    @SysLog("医生备案")
    @ApiOperation(value = "医生备案", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping("/audit/record")
    @PreAuthorize("@p.check('user:doctor:record')")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "doctorId", value = "医生id", required = true, dataType = "long", paramType = "json"),
            @ApiImplicitParam(name = "status", value = "备案状态 0.未备案 1.备案中 2.已备案 3.不通过", required = true, dataType = "int", paramType = "json"),
            @ApiImplicitParam(name = "failureReason", value = "备案审核描述", dataType = "string", paramType = "json"),
    })
    public void recordAudit(@RequestBody String body) throws BusinessException {
        doctorFeignClient.recordAudit(body);
    }

    @ApiOperation(value = "获取完善医师备案信息")
    @ApiImplicitParam(name = "doctorId", value = "医生id", required = true, dataType = "long", paramType = "path")
    @SysLog("获取完善医师备案信息")
    @GetMapping("/record/{doctorId}")
    @PreAuthorize("@p.check('user:doctor:record')")
    public RecordInfoVO recordInfo(@PathVariable Long doctorId) {
        return doctorService.recordInfo(doctorId);
    }

    @ApiOperation(value = "获取医师备案信息")
    @ApiImplicitParam(name = "doctorId", value = "医生id", required = true, dataType = "long", paramType = "path")
    @SysLog("完善医师备案信息")
    @PostMapping("/record")
    @PreAuthorize("@p.check('user:doctor:record')")
    public void updateRecordInfo(@RequestBody RecordInfoVO recordInfoVO) throws BusinessException {
        doctorService.updateRecordInfo(recordInfoVO);
    }

    @SysLog("修改医生账号状态")
    @ApiOperation("修改医生账号状态")
    @GetMapping("/{doctorId}/{status}")
    @PreAuthorize("@p.check('user:doctor:status')")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "doctorId", value = "医生ID", dataType = "long", paramType = "path", required = true),
            @ApiImplicitParam(name = "status", value = "状态 0:正常，1:禁用", dataType = "String", paramType = "path", required = true)
    })
    public void accountStatus(@PathVariable("doctorId") Long doctorId,
                              @PathVariable("status")
                              @Max(value = 1, message = "状态不正确")
                              @Min(value = 0, message = "状态不正确") Integer status) throws BusinessException {
        doctorFeignClient.accountStatus(doctorId, status);
    }

    @SysLog("修改医生账号类别")
    @ApiOperation("修改医生账号类别")
    @GetMapping("/{doctorId}/type")
    @PreAuthorize("@p.check('user:doctor:status')")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "doctorId", value = "医生ID", dataType = "long", paramType = "path", required = true),
            @ApiImplicitParam(name = "type", value = "状态 0:正常，1:测试", dataType = "String", paramType = "form", required = true)
    })
    public void accountType(@PathVariable("doctorId") Long doctorId,
                            @Max(value = 1, message = "状态不正确")
                            @Min(value = 0, message = "状态不正确") Integer type) throws BusinessException {
        doctorFeignClient.accountType(doctorId, type);
    }

    @SysLog("医生信息修改")
    @ApiOperation("医生信息修改")
    @PostMapping("/update")
    @PreAuthorize("@p.check('user:doctor:update')")
    public void update(@RequestBody String body) throws BusinessException {
        doctorFeignClient.update(body);
    }

    @ApiOperation("医生签名文件上传")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "签章图片文件", dataType = "file", paramType = "body", required = true),
            @ApiImplicitParam(name = "doctorId", value = "医生ID", dataType = "long", paramType = "path", required = true)
    })
    @PostMapping("/upload/seal/{doctorId}")
    @PreAuthorize("@p.check('user:doctor:update')")
    public ResponseVO<String> uploadSeal(@NotNull(message = "上传文件不能为null") MultipartFile file,
                                         @PathVariable("doctorId") Long doctorId) throws IOException {
        String url = doctorService.uploadSealImg(file, doctorId);
        return PublicService.returnResponseVO(url);
    }

    /**
     * 城市选择
     *
     * @return
     */
    @ApiOperation("城市选择")
    @ApiImplicitParam(name = "type", value = "城市类型", dataType = "String", paramType = "query", required = true)
    @GetMapping("/city/list")
    public List<CityVO> list(@RequestParam(value = "type", required = false) String type) {
        if (Objects.isNull(type)) {
            type = "all";
        }
        return cityService.queryCityList(type);
    }

    /**
     * 医院选择
     *
     * @return
     */
    @ApiOperation("医院选择")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "cityId", value = "城市ID", dataType = "long", paramType = "path", required = true),
    })
    @GetMapping("/hospital/{cityId}")
    @PreAuthorize("@p.check('user:doctor:hospital:list')")
    public List<HospitalVO> hospital(@PathVariable Long cityId) {
        return doctorService.getHospitalByCityId(cityId);
    }

    /**
     * 获取科室
     *
     * @return
     */
    @ApiOperation("获取科室")
    @ApiImplicitParam(name = "type", value = "科室类型", dataType = "String", paramType = "query", required = true)
    @GetMapping("/department")
    @PreAuthorize("@p.check('user:doctor:department:list')")
    public List<DepartmentVO> getAllDepartment(@RequestParam(value = "type", required = false) Long type) {
        log.info("参数type={}", type);
        return doctorService.getAllDepartment(type);
    }

    /**
     * 民族
     *
     * @return
     */
    @SysLog("民族")
    @ApiOperation("民族")
    @GetMapping("/standard/list")
    @PreAuthorize("@p.check('user:doctor:record')")
    public List<StandardDictVO> getStandardDict() {
        return doctorService.getStandardDict();
    }

    @ApiOperation("上传备案文件")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "file", value = "备案文件", dataType = "__file", paramType = "form", required = true),
        @ApiImplicitParam(name = "doctorId", value = "医生ID", dataType = "long", paramType = "path", required = true),
        @ApiImplicitParam(name = "type", value = "备案文件类型", dataType = "int", paramType = "path", required = true)})
    @PostMapping("/upload/{doctorId}/{type}")
    @PreAuthorize("@p.check('user:doctor:record')")
    public ResponseVO<String> upload(@NotNull(message = "上传文件不能为null") MultipartFile file, @PathVariable Long doctorId,
                                     @PathVariable int type) throws IOException {
        String url = doctorService.uploadFile(doctorId, type, file);
        return PublicService.returnResponseVO(url);
    }

    /**
     * 清除医院缓存
     *
     * @param cityId
     * @return
     */
    @RequestMapping("/hospital/refresh/{cityId}")
    public void refresh(@PathVariable Long cityId) {
        doctorService.removeHospitalCacheByCityId(cityId);
    }

    /**
     * 专家名医列表
     *
     * @return
     */
    @ApiOperation("专家名医列表")
    @SysLog("专家名医列表")
    @GetMapping(value = "expert/list")
    @PreAuthorize("@p.check('user:doctor:expert:list')")
    public PageVO<DoctorPageVO> expertlist(PageParamsVO pageParamsVO, DoctorPageVO doctorVO) {
        log.info("查询专家名医列表： doctorVO={}", doctorVO.toString());
        return doctorService.findExpertPage(pageParamsVO, doctorVO);
    }

    /**
     * 导入专家名医:根据姓名和电话进行匹配
     *
     * @return
     */
    @ApiOperation("导入专家名医")
    @ApiImplicitParam(name = "file", value = "导入模板", dataType = "__file", paramType = "form", required = true)
    @PostMapping(value = "expert/import")
    @PreAuthorize("@p.check('user:doctor:expert:import')")
    public ResponseVO<String> importExpert(MultipartFile file) throws BusinessException {
        return PublicService.returnResponseVO(doctorService.importExpert(file));
    }


    /**
     * 移除专家名医
     */
    @ApiOperation("移除专家名医")
    @ApiImplicitParam(name = "doctorId", value = "医生ID", dataType = "long", paramType = "query", required = true)
    @SysLog("移除专家名医")
    @PostMapping(value = "expert/remove")
    @PreAuthorize("@p.check('user:doctor:expert:remove')")
    public void removeExpert(Long doctorId) {
        doctorService.removeExpert(doctorId);
    }

    /**
     * 专家名医导入模板地址
     *
     * @return
     */
    @ApiOperation("专家名医导入模板地址")
    @SysLog("专家名医导入模板地址")
    @PostMapping(value = "expert/model")
    @PreAuthorize("@p.check('user:doctor:expert:import')")
    public ResponseVO<String> modelExpert() {
        return PublicService.returnResponseVO(doctorService.modelExpert());
    }

    /**
     * 登录登出日志
     */
    @SysLog("APP登录登出日志")
    @ApiOperation("APP登录登出日志")
    @GetMapping(value = "loginlog/list")
    @PreAuthorize("@p.check('user:applog:list')")
    public PageVO<LoginLogVO> appLoginLog(LoginLogVO loginLogParam, PageParamsVO pageParamsVO) throws BusinessException {
        return doctorService.appLoginLog(loginLogParam, pageParamsVO);
    }

    @SysLog("ocr识别")
    @ApiOperation("ocr识别")
    @PostMapping(value = "ocr")
    @PreAuthorize("@p.check('user:doctor:ocr')")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileUrl", value = "文件地址", required = true, dataType = "string", paramType = "from"),
            @ApiImplicitParam(name = "type", value = "类型 1.身份证 2.医师执业证 3.医师资格证", required = true, dataType = "__file", paramType = "from")
    })
    public ResponseVO<String> ocr(@RequestBody @Valid OcrParamVO ocrParamVO) throws BusinessException {
        return PublicService.returnResponseVO(doctorService.ocrDistinguish(ocrParamVO));
    }

  @SysLog("更新某个城市的医院信息")
  @ApiOperation("更新某个城市的医院信息")
  @GetMapping(value = "refrush/hospital")
  public void refrushHospital(Integer cityId) {
    doctorService.removeHospitalCacheByCityId(cityId);
  }

  /**
   * 导入医生信息
   *
   * @return
   */
  @ApiOperation("医生信息导入")
  @PostMapping(value = "expert/import/doctor")
  @PreAuthorize("@p.check('user:doctor:expert:import:doctor')")
  public ResponseVO<String> importExpertDoctor(MultipartFile file) throws BusinessException {
      return PublicService.returnResponseVO(doctorService.importExpertDoctor(file));
  }

  @SysLog("保存证件号")
  @ApiOperation("保存证件号")
  @PostMapping(value = "saveNumber")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "doctorId", value = "医生id", required = true, dataType = "long", paramType = "from"),
      @ApiImplicitParam(name = "number", value = "证件号", required = true, dataType = "string", paramType = "from"),
      @ApiImplicitParam(name = "type", value = "类型：3.执业证 4.身份证 6.资格证", required = true, dataType = "int",
          paramType = "from"),})
  @PreAuthorize("@p.check('user:doctor:saveNumber')")
  public ResponseVO<String> saveNumber(@RequestBody @Valid SaveNumberParamVO saveNumberParamVO)
      throws BusinessException {
      Integer type = saveNumberParamVO.getType();
      if (type.equals(1)) {
          type = 4;
      } else if (type.equals(2)) {
          type = 3;
      } else if (type.equals(3)) {
          type = 6;
      } else {
          type = 0;
      }
      return PublicService.returnResponseVO(
          doctorFeignClient.saveNumber(saveNumberParamVO.getDoctorId(), saveNumberParamVO.getNumber(), type));
  }
}
